package main

import (
	"errors"
	"fmt"
	"net"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"strings"
)

// 检查并设置开机自启
func checkAndSetupAutoStart() {
	if !config.ServerConfig.CheckStartupScript {
		logger.Warn("跳过开机自启设置步骤")
		return
	}

	// 检查是否存在自启动脚本
	saved, err := checkAutoStart()
	if err != nil {
		logger.Error("检查开机自启失败: %v", err.Error())
		return
	}

	// 如果没有创建，则进行创建操作
	if !saved {
		// 检查是否拥有权限
		if err := checkAdminPrivileges(); err != nil {
			logger.Fatalf("权限不足: %v", err)
		}

		// 设置开机自启
		if err := setupAutoStart(); err != nil {
			logger.Printf("开机自启设置失败: %v", err)
		}
	}

}

// 检查是否已经存在开机脚本
func checkAutoStart() (bool, error) {
	switch runtime.GOOS {
	case "linux":
		logger.Info("当前系统为linux，前往/etc/systemd/system检查是否存在自启动脚本")
		servicePath := "/etc/systemd/system/qsbank_proxy.service"
		_, err := os.Stat(servicePath)
		if err != nil && os.IsNotExist(err) {
			logger.Info("开机脚本不存在，即将创建开机脚本")
			return false, nil
		}
		logger.Info("开机脚本已存在，创建开机脚本")
		return true, nil
	case "darwin":
		logger.Info("当前系统为linux，前往/etc/systemd/system检查是否存在自启动脚本")
		homeDir, _ := os.UserHomeDir()
		plistPath := filepath.Join(homeDir, "Library/LaunchAgents/qsbank_proxy.plist")
		_, err := os.Stat(plistPath)
		if err != nil && os.IsNotExist(err) {
			logger.Info("开机脚本不存在，即将创建开机脚本")
			return false, nil
		}
		logger.Info("开机脚本已存在，创建开机脚本")
		return true, nil
	}
	return false, errors.New("不支持的操作系统" + runtime.GOOS + "暂不支持检测是否拥有开机脚本")
}

// 修改开机自启路径中的硬编码问题
func setupAutoStart() error {
	execPath, err := os.Executable()
	if err != nil {
		return err
	}
	switch runtime.GOOS {
	case "linux":
		servicePath := "/etc/systemd/system/qsbank_proxy.service"
		content := fmt.Sprintf(`[Unit]
Description=QS Bank Proxy Service

[Service]
ExecStart=%s
Restart=always

[Install]
WantedBy=multi-user.target`, execPath)
		if err := os.WriteFile(servicePath, []byte(content), 0644); err != nil {
			return err
		}
		// 需要重新加载systemd配置
		if err := exec.Command("systemctl", "daemon-reload").Run(); err != nil {
			return err
		}
		return exec.Command("systemctl", "enable", "qsbank_proxy.service").Run()
	case "darwin":
		homeDir, _ := os.UserHomeDir()
		plistPath := homeDir + "/Library/LaunchAgents/qsbank_proxy.plist"
		content := fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key><string>qsbank_proxy</string>
    <key>ProgramArguments</key>
    <array>
        <string>%s</string>
    </array>
    <key>RunAtLoad</key><true/>
</dict>
</plist>`, execPath)
		if err := os.WriteFile(plistPath, []byte(content), 0644); err != nil {
			return err
		}
		return exec.Command("launchctl", "load", plistPath).Run()
	default:
		return fmt.Errorf("不支持的操作系统: %s", runtime.GOOS)
	}
}

// 程序卸载
func performUninstall() error {
	switch runtime.GOOS {
	case "linux":
		return os.Remove("/etc/systemd/system/qsbank_proxy.service")
	case "darwin":
		homeDir, _ := os.UserHomeDir()
		return os.Remove(filepath.Join(homeDir, "Library/LaunchAgents/qsbank_proxy.plist"))
	default:
		return fmt.Errorf("不支持的操作系统: %s", runtime.GOOS)
	}
}

// 端口检查逻辑
func isPortAvailable(port int) bool {
	addr := fmt.Sprintf(":%d", port)
	listener, err := net.Listen("tcp", addr)
	if err != nil {
		return false
	}
	_ = listener.Close()
	return true
}

// 权限检查
func checkAdminPrivileges() error {
	switch runtime.GOOS {
	case "linux", "darwin":
		output, err := exec.Command("id", "-u").Output()
		if err != nil {
			return fmt.Errorf("检查管理员权限失败: %v", err)
		}
		// 去除输出中的换行符并判断是否为 "0"
		if strings.TrimSpace(string(output)) != "0" {
			return fmt.Errorf("需要管理员权限运行")
		}
	case "windows":
		_, err := os.Open("\\\\.\\PHYSICALDRIVE0")
		if err != nil {
			return fmt.Errorf("需要管理员权限运行")
		}
	default:
		return fmt.Errorf("不支持的操作系统: %s", runtime.GOOS)
	}
	return nil
}

// 设置系统代理
func setSystemProxy() {
	var builder strings.Builder
	// 如果设置了用户名或密码，则需要将代理地址前加上账户名和密码
	if config.ProxyConfig.ProxyUrlUsername != "" && config.ProxyConfig.ProxyUrlPassword != "" {
		// 先按照http://proxy_ip:port进行匹配
		allCompile := regexp.MustCompile(`^([https|http]+:\\/\\/)([\\w-]+(\\.[\\w-]+)+:\\d{1,5}\\/?)$`)
		ipAndPortCompile := regexp.MustCompile(`^([\w-]+(\.[\w-]+)+:\d{1,5}\/?)$`)
		if allCompile.MatchString(config.ProxyConfig.ProxyUrl) {
			submatch := allCompile.FindStringSubmatch(config.ProxyConfig.ProxyUrl)
			builder.WriteString(submatch[1])
			builder.WriteString(config.ProxyConfig.ProxyUrlUsername + ":" + config.ProxyConfig.ProxyUrlPassword + "@")
			builder.WriteString(submatch[2])
		} else if ipAndPortCompile.MatchString(config.ProxyConfig.ProxyUrl) {
			submatch := ipAndPortCompile.FindStringSubmatch(config.ProxyConfig.ProxyUrl)
			builder.WriteString("http://")
			builder.WriteString(config.ProxyConfig.ProxyUrlUsername + ":" + config.ProxyConfig.ProxyUrlPassword + "@")
			builder.WriteString(submatch[2])
		} else {
			logger.Fatal("代理地址格式不正确，请检查配置文件")
		}

	} else {
		// 如果没有账户名或密码，则直接将代理地址写入
		builder.WriteString(config.ProxyConfig.ProxyUrl)
	}

	// 通过环境变量配置代理
	err := os.Setenv("HTTP_PROXY", builder.String())
	if err != nil {
		logger.Fatal("无法通过环境变量配置代理服务器，请检查配置文件")
	}
	err = os.Setenv("HTTPS_PROXY", builder.String())
	if err != nil {
		logger.Fatal("无法通过环境变量配置代理服务器，请检查配置文件")
	}
}
